--
-- VHDL Architecture codec_control.codec_control.arch
--
-- Created:
--          by - toban963.student (southfork-14.edu.isy.liu.se)
--          at - 10:39:18 10/04/11
--
-- using Mentor Graphics HDL Designer(TM) 2008.1 (Build 17)
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;

ENTITY codec_control IS
  PORT( 
  reset_n : IN std_logic;
  sys_clk     : IN     std_logic;
  AUD_ADCLRCK : INOUT  std_logic;
  AUD_ADCDAT  : IN     std_logic;
  AUD_DACLRCK : INOUT  std_logic;
  AUD_DACDAT  : OUT    std_logic;
  AUD_BCLK    : INOUT  std_logic;
  I2C_SCLK    : OUT    std_logic;
  I2C_SDAT    : INOUT  std_logic
  );
  -- Declarations
  type exemplar_string_array is array (natural range <>, natural range <>) of character;
  attribute pin_number : string;
  attribute array_pin_number : exemplar_string_array;
  attribute pin_number of sys_clk : signal is "PIN_D17";--AUD_XCK??
  attribute pin_number of AUD_ADCLRCK : signal is "PIN_E19";
  attribute pin_number of AUD_ADCDAT : signal is "PIN_E19";
  attribute pin_number of AUD_DACLRCK : signal is "PIN_G18";
  attribute pin_number of AUD_DACDAT : signal is "PIN_F18";
  attribute pin_number of AUD_BCLK : signal is "PIN_E17";
  attribute pin_number of I2C_SCLK : signal is "PIN_J18";
  attribute pin_number of I2C_SDAT : signal is "PIN_H18";
  
END codec_control ;

--
ARCHITECTURE arch OF codec_control IS
SIGNAL temp_sign: std_logic_vector(0 TO 7);
SIGNAL I2C_SCLK_temp: std_logic;
SIGNAL I2C_DATA_fall: std_logic;
SIGNAL clk_end: integer range 0 to 54;
SIGNAL clk_counter:integer range 0 to 125;
SIGNAL init_end: std_logic;
SIGNAL I2C_SCLK_rising: std_logic;
SIGNAL AUD_BCLK_last: std_logic;
SIGNAL AUD_BCLK_rising: std_logic;
SIGNAL right_aud_data_reg: std_logic_vector(23 DOWNTO 0);
SIGNAL left_aud_data_reg: std_logic_vector(23 DOWNTO 0);
BEGIN
  
  PROCESS(sys_clk) --Generating the I2C-clock
    BEGIN
      if sys_clk'event and sys_clk='1' then
        if I2C_DATA_fall = '1' then  
          if clk_end = 54 then
            I2C_DATA_fall <='0';   
          elsif clk_counter = 125 then
            I2C_SCLK <= NOT I2C_SCLK_temp;
            I2C_SCLK_temp <= NOT I2C_SCLK_temp;
            clk_counter<=0;
            clk_end<=clk_end+1;
            IF I2C_SCLK_temp = '0' THEN
              I2C_SCLK_rising <= '1';
            END IF;
          else
            clk_counter<=clk_counter+1;
          end if;
        end if;
      end if;
    END PROCESS;
    
    PROCESS(reset_n)
      BEGIN
        IF reset_n = '0' THEN
        I2C_SCLK <= '1';
        I2C_SCLK_temp <= '1';
        I2C_DATA_fall <= '1';
        i2c_sdat <= '1';
      END IF;
      END PROCESS;
      
      
      PROCESS(sys_clk)
        VARIABLE count: integer range 0 TO 9 := 9;
        VARIABLE count2: integer range 0 TO 3;
        BEGIN
          IF rising_edge(sys_clk) THEN
            IF init_end = '0' then
              
              CASE count2 is
              when 0 => temp_sign <= "00110101"; -- address and write bit
              when 1 => temp_sign <= "00001110"; -- register (15 downto 8)
              when 2 => temp_sign <= "00001010"; -- data (7 downto 0)
              when others => NULL;
              END CASE;
              
              if count = 9 then
                i2c_sdat <= '0';
                count := 0;
              end if;
              
              
              IF I2C_SCLK_rising = '1' THEN
                I2C_SCLK_rising <= '0';
                
                
                IF count < 8 THEN
                  count := count + 1;
                  i2c_sdat <= temp_sign(count);  
                ELSIF count = 8 THEN
                  IF count2 = 2 THEN
                    init_end <= '1';
                  ElSE
                    count := 0;
                    count2 := count2 + 1;	
                  END IF;
                  
                  
                END IF;
              END IF;
            END IF;
          END IF;
        END PROCESS;
        
        
        
        
        PROCESS(sys_clk)
          BEGIN
            IF rising_edge(sys_clk) THEN
              IF AUD_BCLK_last = AUD_BCLK THEN
                AUD_BCLK_last <= AUD_BCLK;
              ELSIF AUD_BCLK_last = '0' THEN
                AUD_BCLK_rising <= '1';
              END IF;
            END IF;
            
          END PROCESS;
          
          
          
          PROCESS(sys_clk) -- Assuming left justified
            VARIABLE count3: integer range 0 to 23;
            BEGIN
              IF rising_edge(sys_clk) THEN
                IF AUD_BCLK_RISING = '1' THEN
                  AUD_BCLK_RISING <= '0';
                  
                  IF count3 = 23 THEN -- when bitclock has changed 24 times change read left/right data
                    count3 := 0;
                    AUD_ADCLRCK <= NOT AUD_ADCLRCK;
                  ELSE
                    count3 := count3 + 1;
                  END IF;
                  
                  IF AUD_ADCLRCK = '0' THEN --reads bits when right channel selected
                    right_aud_data_reg(23 DOWNTO 1) <= right_aud_data_reg(22 DOWNTO 0);
                    right_aud_data_reg(0) <= aud_adcdat;
                  ELSIF AUD_ADCLRCK = '1' THEN --reads bits when left channel selected
                    left_aud_data_reg(23 DOWNTO 1) <= left_aud_data_reg(22 DOWNTO 0);
                    left_aud_data_reg(0) <= aud_adcdat;
                  END IF;
                END IF;
              END IF;
            END PROCESS;
            
          END ARCHITECTURE arch;
          
          
          
          
          
          
          